package elev.sim;

import java.util.ArrayList;

/**
 *
 * Symulacja - kolejność wywoływania metod: wysadzPasazerow(); wezPasazerow();
 * jedzNaPietro();
 *
 * @author Marcin Samułek & Michal Jarzyna
 */
public class Winda {

    private int czas;           //czas w ktorym winda pracuje
    private int numerWindy;     //pomocnym jest to kiedy winda wie kim jest
    boolean czyUruchomiona;     //TODO get set i private
    private int pietro;        //aktualne pietro
    private boolean tryb;       //tryb gora dol
    private int pojemnosc;     // max pojemnosc windy
    private ArrayList<Integer> kolejkaWezwan;        //wezwania
    private ArrayList<Pasazer> kolejkaRozwozenia;   //pasazerowie w windzie do rozwiezienia
    private int aktualnyCel;   //aktualny cel windy

    Winda(boolean tryb, int poj) {
        czas = 0;
        this.pietro = 0;
        this.tryb = tryb;
        this.pojemnosc = poj;
        this.aktualnyCel = -1;
        this.kolejkaWezwan = new ArrayList<>();
        this.kolejkaRozwozenia = new ArrayList<>();
    }

    /**
     *
     * @param p
     */
    public boolean obsluzZdarzenie(Pietro p) {
        this.wysadzPasazerow(p);
        boolean ret = this.wezPasazerow(p);
        return ret;
    }

    /**
     * Jedz na pierwsze w kolejce pietro lub pietro wybrane przez pasazerow.
     * Winda najpierw rozwozi osoby znajdujace się w windzie, później jedzie do
     * wezwań
     *
     */
    public void ustawWinde() {
        if (this.kolejkaRozwozenia.isEmpty()) {
            if (!this.kolejkaWezwan.isEmpty()) {
                this.aktualnyCel = this.kolejkaWezwan.get(0);
                this.kolejkaWezwan.remove(0);
            }
        } else {
            this.aktualnyCel = this.kolejkaRozwozenia.get(0).getPietroDocelowe();
        }
    }

    /**
     * poruszanie winda miedzy pietrami.
     */
    public void jedz() {
        if (this.pietro != this.aktualnyCel) {
            if (this.pietro > this.aktualnyCel) {
                this.pietro--;
                Statystyki.dodajPrzejechanePietro(numerWindy);
                Log.pietroWindy(numerWindy, pietro);
            } else {
                this.pietro++;
                Statystyki.dodajPrzejechanePietro(numerWindy);
                Log.pietroWindy(numerWindy, pietro);
            }



        } else {
            this.aktualnyCel = -1;
        }
        if (this.pietro == this.aktualnyCel) {
            this.aktualnyCel = -1;
        }
    }

    /**
     * zabiera pasażera z piętra
     *
     * @param p
     */
    public boolean wezPasazerow(Pietro p) {
        int iloscOsobZabranych = 0;
        while (this.czyWolneMiejsce() > 0 && p.getOczekujacy() > 0) {
            kolejkaRozwozenia.add(p.usunPasazera());
            iloscOsobZabranych++;
        }
        if (iloscOsobZabranych > 0) {
            Log.wezPasazerow(numerWindy, pietro, iloscOsobZabranych);
        }

        this.resetQueue(this.pietro);
        p.resetButtons();

        if (p.getOczekujacy() != 0) {
            p.pushButtons();
            return false;
        }
        return true;
    }

    private void resetQueue(int numerPietra) {
        int i = 0;
        while (i < this.kolejkaWezwan.size()) {
            if (numerPietra == this.kolejkaWezwan.get(i)) {
                this.kolejkaWezwan.remove(i);
            } else {
                i++;
            }
        }
    }

    /**
     * sprawdza ile w windzie jest wolnego miejsca.
     *
     * @return
     */
    private int czyWolneMiejsce() {
        return this.pojemnosc - this.kolejkaRozwozenia.size();
    }

    /**
     * przenosi pasazerow na pietro ich celu podrozy
     *
     * @param p
     */
    public void wysadzPasazerow(Pietro p) {

        p.dodajPrzywiezionego(this.usunPasazera());
    }

    /**
     * jesli pasazerowie wysiadaja to ich usuwa i zwraca listę osob ktore
     * wysiadły
     *
     * @return
     */
    public ArrayList<Pasazer> usunPasazera() {
        int i = 0;
        ArrayList<Pasazer> wysiadajacy = new ArrayList<>();
        while (i < this.kolejkaRozwozenia.size()) {
            if (this.kolejkaRozwozenia.get(i).getPietroDocelowe() == this.pietro) {
                wysiadajacy.add(this.kolejkaRozwozenia.get(i));
                Statystyki.dodajRozwiezionaOsobe(numerWindy);
                this.kolejkaRozwozenia.remove(i);
            } else {
                i++;
            }
        }
        if (wysiadajacy.size() > 0) {
            Log.wysadzPasazerow(numerWindy, pietro, wysiadajacy.size());
        }
        return wysiadajacy;
    }

    /**
     *
     * @param n
     */
    public void dodajWezwanie(int n) {
        this.kolejkaWezwan.add(n);
    }

    /**
     *
     * @return
     */
    public int ilePas() {
        return this.pojemnosc - this.czyWolneMiejsce();
    }

    /**
     *
     * @return
     */
    public int getCel() {
        return this.aktualnyCel;
    }

    /**
     *
     * @return
     */
    public int getPietro() {
        return this.pietro;
    }

    public void setPietro(int pietro) {
        this.pietro = pietro;
    }

    /**
     *
     * @return
     */
    public boolean getTryb() {
        return this.tryb;
    }

    public int getNumerWindy() {
        return numerWindy;
    }

    public void setNumerWindy(int numerWindy) {
        this.numerWindy = numerWindy;
    }

    public void switchTryb() {
        this.tryb = (this.tryb == true) ? false : true;
    }
}
